package com.define.commons.quartz.utils;

import com.define.commons.quartz.domain.Task;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Date;

/**
 * 定时任务CRUD的工具类
 * @Author xiewenlong
 * @Date 2018/11/21 9:27
 */
@Component
public class QuartzUtil {
    public static final String DEFAULT_JOB_DATA_KEY = "PARAM";
    public static final String DEFAULT_JOB_GROUP_NAME = "DEFAULT_JOB_GROUP_NAME";
    public static final String DEFAULT_TRIGGER_GROUP_NAME = "DEFAULT_TRIGGER_GROUP_NAME";

    @Autowired
    private Scheduler scheduler;

    /**
     * 根据任务添加一个工作
     */
    public void addJob(Task task) throws Exception {
        //有效性判断
        if(StringUtils.isEmpty(task.getJobName())){
            throw new RuntimeException("JobName is empty!");
        }
        if(!CronExpression.isValidExpression(task.getCronExpression())){
            throw new RuntimeException("CronExpression is valid!");
        }
        if(StringUtils.isEmpty(task.getClazz())){
            throw new RuntimeException("Execution class is empty!");
        }
        //默认值设置
        if(StringUtils.isEmpty(task.getJobGroupName())){
            task.setJobGroupName(DEFAULT_JOB_GROUP_NAME);
        }
        if(StringUtils.isEmpty(task.getTriggerGroupName())){
            task.setTriggerGroupName(DEFAULT_TRIGGER_GROUP_NAME);
        }
        if(StringUtils.isEmpty(task.getTriggerName())){
            task.setTriggerName(task.getJobName());
        }
        //任务调度
        //加载执行类
        Class executeClazz = Class.forName(task.getClazz());
        //创建工作任务
        JobDetail jobDetail = JobBuilder.newJob(executeClazz)
                .withIdentity(task.getJobName(), task.getJobGroupName())
                .withDescription(task.getRemark())
                .usingJobData(DEFAULT_JOB_DATA_KEY, task.getParam())
                .build();
        //表达式调度构建器(哑火策略为忽略所有哑火，在下个周期执行)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                .cronSchedule(task.getCronExpression())
                .withMisfireHandlingInstructionDoNothing();
        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(task.getJobName(), task.getJobGroupName())
                .withSchedule(scheduleBuilder)
                .withDescription(task.getRemark())
                .usingJobData(DEFAULT_JOB_DATA_KEY, task.getParam())
                .startAt(new Date())
                .forJob(jobDetail)
                .build();
        //调度任务并保存
        scheduler.scheduleJob(jobDetail, trigger);
    }

    /**
     * 获取Job状态
     */
    public String getJobState(String jobName, String jobGroupName) throws SchedulerException {
        TriggerKey triggerKey = new TriggerKey(jobName, jobGroupName);
        return scheduler.getTriggerState(triggerKey).name();
    }

    /**
     * 暂停所有任务
     */
    public void pauseAllJob() throws SchedulerException {
        scheduler.pauseAll();
    }

    /**
     * 暂停任务
     */
    public void pauseJob(String jobName, String jobGroupName) throws Exception {
        JobKey jobKey = new JobKey(jobName, jobGroupName);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if (jobDetail == null) {
            throw new RuntimeException("JobDetail is null!");
        }else {
            scheduler.pauseJob(jobKey);
        }
    }

    /**
     * 恢复所有任务
     */
    public void resumeAllJob() throws Exception {
        scheduler.resumeAll();
    }

    /**
     * 恢复某个任务
     */
    public void resumeJob(String jobName, String jobGroupName) throws Exception {
        JobKey jobKey = new JobKey(jobName, jobGroupName);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if (jobDetail == null) {
            throw new RuntimeException("JobDetail is null!");
        }else {
            scheduler.resumeJob(jobKey);
        }
    }

    /**
     * 删除某个任务
     */
    public boolean deleteJob(String jobName, String jobGroupName) throws Exception {
        JobKey jobKey = new JobKey(jobName, jobGroupName);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if (jobDetail == null ) {
            throw new RuntimeException("JobDetail is null!");
        }else if(!scheduler.checkExists(jobKey)) {
            throw new RuntimeException("JobKey is not exists!");
        }else {
            return scheduler.deleteJob(jobKey);
        }
    }

    /**
     * 修改任务
     */
    public void modifyJob(Task task) throws Exception {
        if (!CronExpression.isValidExpression(task.getCronExpression())) {
            throw new RuntimeException("CronExpression is valid!");
        }
        TriggerKey triggerKey = TriggerKey.triggerKey(task.getJobName(),task.getJobGroupName());
        JobKey jobKey = new JobKey(task.getJobName(),task.getJobGroupName());
        if (scheduler.checkExists(jobKey) && scheduler.checkExists(triggerKey)) {
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            //表达式调度构建器(哑火策略为忽略所有哑火，在下个周期执行)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                    .cronSchedule(task.getCronExpression())
                    .withMisfireHandlingInstructionDoNothing();
            //按新的cronExpression表达式重新构建trigger
            trigger = trigger
                    .getTriggerBuilder()
                    .withIdentity(triggerKey)
                    .withSchedule(scheduleBuilder)
                    .build();
            //修改参数
            if(!trigger.getJobDataMap().get(DEFAULT_JOB_DATA_KEY).equals(task.getParam())) {
                trigger.getJobDataMap().put(DEFAULT_JOB_DATA_KEY,task.getParam());
            }
            //按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
        }else {
            throw new RuntimeException("Job or Trigger not exists!");
        }
    }

}
